import json

from bson.objectid import ObjectId

from api_base import *
from docker_client import *


class APILabDetailHandler(APIBaseHandler):
    ALLOW_FIELDS = ['image', 'command', 'pids_limit',
                    'mem_limit', 'cpu_period', 'cpu_quota']

    @check_role(RoleStudent)
    async def get(self):
        '''
        获得课程信息
        '''
        labidstr = get_id(self.request.uri)
        labid = ObjectId(labidstr)
        res = await self.db.labs.find_one({'_id': labid})
        if not res:
            self.write_json({'info': 'unknown lab'})
            return
        res.pop('_id')
        if self.role < RoleTeacher:
            res.pop('image')
        res2 = await self.db.containers.find_one({'username': self.current_user, 'labid': labid})
        if res2:
            res['containerid'] = res2['containerid']
        self.write_json(res)

    @check_role(RoleStudent)
    async def post(self):
        '''
        获取开始暂停结束实验
        '''
        labidstr = get_id(self.request.uri)
        labid = ObjectId(labidstr)
        try:
            js = json.loads(self.request.body)
            op = js['op']
        except:
            self.write_json({'info': 'json_error'})
            return
        if op == 'create':
            # TODO sql optimize
            res = await self.db.containers.find_one({'username': self.current_user, 'labid': labidstr})
            if res:
                self.write_json(
                    {'info': 'opened', 'containerid': res['containerid']})
                return
            res = await self.db.labs.find_one({'_id': labid})
            if not res:
                self.write_json({'info': 'unknown lab'})
                return
            res = await self.db.images.find_one({'image': res['image']})
            if not res:
                self.write_json({'info': 'unknown image'})
                return
            res.pop('_id')
            res = {k: res[k] for k in self.ALLOW_FIELDS if res.get(k)}
            res.update(container_common_args)
            con = await create_container(res)
            res = await self.db.containers.insert_one({'username': self.current_user, 'labid': labidstr, 'containerid': con.id})
            self.write_json({'info': 'ok', 'containerid': con.id})
        elif op == 'stop':
            res = await self.db.containers.find_one({'username': self.current_user, 'labid': labidstr})
            if res:
                con = await get_container(res['containerid'])
                await stop_container(con)
                self.write_json({'info': 'ok', 'containerid': con.id})
            else:
                self.write_json({'info': 'unknown container'})
        elif op == 'remove':
            res = await self.db.containers.find_one_and_delete({'username': self.current_user, 'labid': labidstr})
            if res:
                con = await get_container(res['containerid'])
                await stop_and_remove_container(con)
                self.write_json({'info': 'ok', 'containerid': con.id})
            else:
                self.write_json({'info': 'unknown container'})
        elif op == 'get':
            res = await self.db.containers.find_one({'username': self.current_user, 'labid': labidstr})
            self.write_json({'info': 'ok', 'containerid': res['containerid']})
        else:
            self.write_json({'info': 'unknown op'})


class APILabAdminHandler(APIBaseHandler):
    @check_role(RoleTeacher)
    async def get(self):
        '''
        获取学生实验
        '''
        labidstr = get_id(self.request.uri)
        labid = ObjectId(labidstr)
        containers = []
        async for item in self.db.containers.find({'labid': labidstr}):
            containers.append({
                'username': item['username'],
                'containerid': item['containerid']
            })
        self.write_json(containers)

    @check_role(RoleTeacher)
    async def post(self):
        pass
